package trading.algo.BearTask;

import java.util.Timer;
import java.util.TimerTask;

import trading.algo.MasterAlgo;
import trading.algo.MasterAlgoStartUpTask;
import trading.algo.OpenOrdersTask;
import trading.algo.TimerKillerTask;
import trading.algo.UpdateAccountValueTask;
import trading.algo.APIConnectivityTask.APIConnectMasterTask;
import trading.algo.initTask.HistoricalLowTask;
import trading.algo.initTask.LastClosePriceTask;
import trading.bo.DBAccessorBO;
import trading.bo.EmailAccessorBO;
import trading.bo.IBAccessorBO;
import trading.dataentry.MonitoredStocks;
import trading.util.MarketTimeHelper;
import trading.util.OrderSplitHelper;

public class AfterMarketHourTask extends TimerTask {

    private MasterAlgo masterAlgo;
    private IBAccessorBO ibAccessorBO;
    private DBAccessorBO dbAccessorBO;
    private EmailAccessorBO emailAccessorBO;
    private MarketTimeHelper marketTimeHelper;
    private OrderSplitHelper orderSplitHelper;

    public AfterMarketHourTask(MasterAlgo masterAlgo,
            IBAccessorBO ibAccessorBO, DBAccessorBO dbAccessorBO, EmailAccessorBO emailAccessorBO,
            MarketTimeHelper marketTimeHelper, OrderSplitHelper orderSplitHelper) {
        this.masterAlgo = masterAlgo;
        this.ibAccessorBO = ibAccessorBO;
        this.dbAccessorBO = dbAccessorBO;
        this.emailAccessorBO = emailAccessorBO;
        this.marketTimeHelper = marketTimeHelper;
        this.orderSplitHelper = orderSplitHelper;
    }

    @Override
    public void run() {
        Timer timer = new Timer();

        int taskID = 0;
        // try connect to IB, just in case
        APIConnectMasterTask apiConnectMasterTask = new APIConnectMasterTask(ibAccessorBO);
        timer.schedule(apiConnectMasterTask, taskID * 1000);
        taskID += APIConnectMasterTask.secondsNeeded();
        
        // Specific task for bear market...
        // sync VIX spot price and future prices
        VIXPricesTask vixPricesTask = new VIXPricesTask(this.dbAccessorBO,
                this.ibAccessorBO, marketTimeHelper);
        timer.schedule(vixPricesTask, taskID * 1000);
        taskID += VIXPricesTask.secondsNeeded();

        // sync the open orders
        OpenOrdersTask openOrderTask = new OpenOrdersTask(ibAccessorBO,
                dbAccessorBO);
        timer.schedule(openOrderTask, taskID * 1000);
        taskID += OpenOrdersTask.secondsNeeded();

        // create orders if bear market criteria is met
        OrderCreationTask orderCreationTask = new OrderCreationTask(
                this.dbAccessorBO, this.ibAccessorBO, emailAccessorBO, orderSplitHelper);
        timer.schedule(orderCreationTask, taskID * 1000);
        taskID += OrderCreationTask.secondsNeeded();

        // sync the last closing price of stock tickers
        for (int i = 0; i < MonitoredStocks.TICKERS.values().length; i++, taskID += LastClosePriceTask
                .secondsNeeded()) {
            MonitoredStocks.TICKERS ticker = MonitoredStocks.TICKERS.values()[i];
            timer.schedule(new LastClosePriceTask(ticker.name(), ibAccessorBO),
                    taskID * 1000);
        }

        // sync the date of stock historical low price
        for (int i = 0; i < MonitoredStocks.TICKERS.values().length; i++, taskID += HistoricalLowTask
                .secondsNeeded()) {
            MonitoredStocks.TICKERS ticker = MonitoredStocks.TICKERS.values()[i];
            timer.schedule(new HistoricalLowTask(ticker.name(), ibAccessorBO),
                    taskID * 1000);
        }

        // sync the open orders
        timer.schedule(new OpenOrdersTask(ibAccessorBO, dbAccessorBO),
                taskID * 1000);
        taskID += OpenOrdersTask.secondsNeeded();

        // sync the account status and portfolio positions
        timer.schedule(new UpdateAccountValueTask(ibAccessorBO, dbAccessorBO, true),
                taskID * 1000);
        taskID += UpdateAccountValueTask.secondsNeeded();
        
        // schedule next trading day task
        timer.schedule(new MasterAlgoStartUpTask(masterAlgo), taskID * 1000);
        taskID += MasterAlgoStartUpTask.secondsNeeded();

        // kill the timer
        timer.schedule(new TimerKillerTask(timer), taskID * 1000);

    }

    public static int secondsNeeded() {
        return APIConnectMasterTask.secondsNeeded()
                + VIXPricesTask.secondsNeeded()
                + OpenOrdersTask.secondsNeeded()
                + OrderCreationTask.secondsNeeded()
                + LastClosePriceTask.secondsNeeded() * 5
                + HistoricalLowTask.secondsNeeded() * 5
                + OpenOrdersTask.secondsNeeded()
                + MasterAlgoStartUpTask.secondsNeeded();
    }

}
